﻿using System;
using System.Text;
using System.IO;

namespace M
{
	/// <summary>
	/// 友情IO类
	/// </summary>
	public static class MIO
	{
		/// <summary>
		/// 将多个路径参数拼接为完整路径
		/// </summary>
		/// <param name="pathArgs">路径参数</param>
		/// <returns>拼接后的完整路径</returns>
		public static string GetPath(params string[] pathArgs)
		{
			MValidator.CheckForNullReference("Paths", pathArgs);
			MValidator.CheckValueMinLimit<int>("Path Length", pathArgs.Length, 1);
			if (pathArgs.Length == 1)
				return pathArgs[0];
			string path = pathArgs[0];
			for (int i = 1; i < pathArgs.Length; i++)
				path = Path.Combine(path, pathArgs[i]);
			return path;
		}
		/// <summary>
		/// 从路径中获取文件夹/文件名
		/// </summary>
		/// <param name="path">路径</param>
		/// <param name="spliter">分隔符 / or \</param>
		/// <returns></returns>
		public static string GetEntryName(string path, char spliter)
		{
			MValidator.CheckForEmptyString("Entry Path", path);
			return path.Substring(
				path.LastIndexOf(spliter) + 1,
				path.Length - path.LastIndexOf(spliter) - 1
				);
		}
		/// <summary>
		/// 获取系统唯一临时文件路径
		/// </summary>
		/// <param name="keepFile">是否保留文件：如果不保留文件则会删除申请唯一临时文件时简历的文件</param>
		/// <returns>文件路径</returns>
		public static string GetTempFileName(bool keepFile)
		{
			string path = System.IO.Path.GetTempFileName();
			if (!keepFile)
			{
				if (System.IO.File.Exists(path))
					System.IO.File.Delete(path);
			}
			return path;
		}
		/// <summary>
		/// 创建文件夹
		/// 若存在则继续不提示错误
		/// </summary>
		/// <param name="path">需要创建的文件夹路径</param>
		public static DirectoryInfo CreateDirectory(string path)
		{
			return CreateDirectory(path, true);
		}
		/// <summary>
		/// 创建文件夹
		/// 若存在则根据参数决定是否继续
		/// </summary>
		/// <param name="path">需要创建的文件夹路径</param>
		/// <param name="allowexists">是否允许存在</param>
		public static DirectoryInfo CreateDirectory(string path, bool allowexists)
		{
			MValidator.CheckForEmptyString("Directory Path", path);
			// 检查文件夹是否已存在
			if (Directory.Exists(path))
			{
				if (!allowexists)
					throw new ArgumentException("directory already exists");
			}
			// 创建文件夹
			return Directory.CreateDirectory(path);
		}
		/// <summary>
		/// 获取类型所对应程序集DLL所在的目录
		/// </summary>
		/// <param name="type">类型</param>
		/// <returns>返回DLL所在目录</returns>
		public static string GetAssemblyDirectory(Type type)
		{
			string executePath = type.Assembly.Location;
			string workingPath = executePath.Substring(0, executePath.LastIndexOf("\\") + 1);
			return workingPath;
		}
		/// <summary>
		/// 获取App工作目录
		/// 支持IDE插件，桌面App，已部署到IIS的WebApp
		/// </summary>
		/// <param name="caller"></param>
		/// <returns></returns>
		public static string GetWorkingDirectoryPath(object caller)
		{
			// 获取执行文件名称
			string executableFilePath = Win.Util.GetCurrentFilePath();
			string executableFileName = executableFilePath.Substring(executableFilePath.LastIndexOf("\\") + 1);
			// IDE插件，返回程序集所在目录
			switch (executableFileName.ToLower())
			{
				case "devenv.exe":
					return MIO.GetAssemblyDirectory(caller.GetType());
				case "w3wp.exe":
					return System.Web.HttpContext.Current.Server.MapPath("~/");
				default:
					return Win.Util.GetCurrentDirectory();
			}
		}

		/// <summary>
		/// 从文件中获取文本
		/// 根据文件编码自动判断编码
		/// 若无法获取则使用系统默认编码
		/// </summary>
		/// <param name="path">文件路径</param>
		/// <returns>文件中的文本</returns>
		public static string LoadText(string path)
		{
			return LoadText(path, GetEncoding(path, System.Text.Encoding.Default));
		}

		/// <summary>
		/// 从文件中获取文本
		/// 并传递指定编码
		/// </summary>
		/// <param name="path">文件路径</param>
		/// <param name="encoding">文件编码</param>
		/// <returns>文件中的文本</returns>
		public static string LoadText(string path, System.Text.Encoding encoding)
		{
			MValidator.CheckForEmptyString("File Path", path);
			encoding = encoding ?? System.Text.Encoding.Default;
			using (StreamReader sr = new StreamReader(path, encoding))
			{
				return sr.ReadToEnd();
			}
		}

		/// <summary>
		/// 以系统默认编码以覆盖形式保存文本到文件
		/// </summary>
		/// <param name="path">文件路径</param>
		/// <param name="txt">文本</param>
		public static void SaveText(string path, string txt)
		{
			SaveText(path, txt, false);
		}

		/// <summary>
		/// 以系统默认编码保存文本到文件
		/// </summary>
		/// <param name="path">文件路径</param>
		/// <param name="txt">文本</param>
		/// <param name="append">是否追加</param>
		public static void SaveText(string path, string txt, bool append)
		{
			SaveText(path, txt, append, System.Text.Encoding.Default);
		}

		/// <summary>
		/// 保存文本到文件
		/// </summary>
		/// <param name="path">文件路径</param>
		/// <param name="txt">文本</param>
		/// <param name="append">是否追加</param>
		/// <param name="encoding">编码</param>
		public static void SaveText(string path, string txt, bool append, System.Text.Encoding encoding)
		{
			MValidator.CheckForEmptyString("File Path", path);
			encoding = encoding ?? System.Text.Encoding.Default;
			using (StreamWriter sw = new StreamWriter(path, append, encoding))
			{
				sw.WriteLine(txt);
				sw.Flush();
			}
		}

		#region 根据文件自身取得编码
		/// <summary>
		/// 取得一个文本文件的编码方式。如果无法在文件头部找到有效的前导符，Encoding.Default将被返回。
		/// </summary>
		/// <param name="fileName">文件名。</param>
		/// <returns></returns>
		public static Encoding GetEncoding(string fileName)
		{
			return GetEncoding(fileName, Encoding.Default);
		}
		/// <summary>
		/// 取得一个文本文件流的编码方式。
		/// </summary>
		/// <param name="stream">文本文件流。</param>
		/// <returns></returns>
		public static Encoding GetEncoding(FileStream stream)
		{
			return GetEncoding(stream, Encoding.Default);
		}
		/// <summary>
		/// 取得一个文本文件的编码方式。
		/// </summary>
		/// <param name="fileName">文件名。</param>
		/// <param name="defaultEncoding">默认编码方式。当该方法无法从文件的头部取得有效的前导符时，将返回该编码方式。</param>
		/// <returns></returns>
		public static Encoding GetEncoding(string fileName, Encoding defaultEncoding)
		{
			FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
			Encoding targetEncoding = GetEncoding(fs, defaultEncoding);
			fs.Close();
			return targetEncoding;
		}
		/// <summary>
		/// 取得一个文本文件流的编码方式。
		/// </summary>
		/// <param name="stream">文本文件流。</param>
		/// <param name="defaultEncoding">默认编码方式。当该方法无法从文件的头部取得有效的前导符时，将返回该编码方式。</param>
		/// <returns></returns>
		public static Encoding GetEncoding(FileStream stream, Encoding defaultEncoding)
		{
			Encoding targetEncoding = defaultEncoding;
			if (stream != null && stream.Length >= 2)
			{
				//保存文件流的前4个字节
				byte byte1 = 0;
				byte byte2 = 0;
				byte byte3 = 0;
				byte byte4 = 0;
				//保存当前Seek位置
				long origPos = stream.Seek(0, SeekOrigin.Begin);
				stream.Seek(0, SeekOrigin.Begin);

				int nByte = stream.ReadByte();
				byte1 = Convert.ToByte(nByte);
				byte2 = Convert.ToByte(stream.ReadByte());
				if (stream.Length >= 3)
				{
					byte3 = Convert.ToByte(stream.ReadByte());
				}
				if (stream.Length >= 4)
				{
					byte4 = Convert.ToByte(stream.ReadByte());
				}
				//根据文件流的前4个字节判断Encoding
				//Unicode {0xFF, 0xFE};
				//BE-Unicode {0xFE, 0xFF};
				//UTF8 = {0xEF, 0xBB, 0xBF};
				if (byte1 == 0xFE && byte2 == 0xFF)//UnicodeBe
				{
					targetEncoding = Encoding.BigEndianUnicode;
				}
				if (byte1 == 0xFF && byte2 == 0xFE && byte3 != 0xFF)//Unicode
				{
					targetEncoding = Encoding.Unicode;
				}
				if (byte1 == 0xEF && byte2 == 0xBB && byte3 == 0xBF)//UTF8
				{
					targetEncoding = Encoding.UTF8;
				}
				//恢复Seek位置       
				stream.Seek(origPos, SeekOrigin.Begin);
			}
			return targetEncoding;
		}
		#endregion

		/// <summary>
		/// 把int32类型的数据转存到4个字节的byte数组中  
		/// </summary>
		/// <param name="m"></param>
		/// <returns></returns>
		public static byte[] ConvertInt32ToByteArray(Int32 m)
		{
			byte[] array = new byte[4];
			array[0] = (byte)(m & 0xFF);
			array[1] = (byte)((m & 0xFF00) >> 8);
			array[2] = (byte)((m & 0xFF0000) >> 16);
			array[3] = (byte)((m >> 24) & 0xFF);

			return array;
		}  
	}
}
